package com.guchenbo.example.lock;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author guchenbo
 * @date 2022/3/23
 */
public class TestCondition {
    public static void print(Object object) {
        System.out.println(Thread.currentThread().getName() + " -> " + object);
    }

    public static void main(String[] args) {
        ReentrantLock lock = new ReentrantLock();
        Condition empty = lock.newCondition();
        Condition notEmpty = lock.newCondition();
        ExecutorService executor = Executors.newSingleThreadExecutor();

        ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(10);

        /*
        1、生产者和消费者需要相互唤醒，因此需要同一个lock对象，用同一把锁
        2、同一把锁，生产者和消费者相互竞争
         */

        List<String> list = new ArrayList<>();
        // 生产者一直生产
        executor.submit(() -> {
            while (true) {
                lock.lock();
                try {
                    //product
                    if (list.size() == 1) {
                        // 仓库满了，等待消费
                        empty.await();
                        // 防止意外唤醒，因此重新需要获取当前仓库的状态
                        continue;
                    }
                    String uuid = UUID.randomUUID().toString().replaceAll("-", "");
                    list.add(uuid);
                    // 提醒消费
                    notEmpty.signal();
                    print("product => " + list.get(0));
                } catch (Exception e) {
                    e.printStackTrace();
                    break;
                } finally {
                    lock.unlock();
                }
            }
        });

        for (int i = 0; i < 3; i++) {
            // 三个消费者，不停的消费
            scheduled.scheduleAtFixedRate(() -> {
                while (true) {
                    lock.lock();
                    try {
                        //consume
                        if (list.size() == 0) {
                            // 仓库空了，等待生产
                            notEmpty.await();
                            // 防止意外唤醒，因此重新需要获取当前仓库的状态
                            continue;
                        }
                        String uuid = list.remove(0);
                        print("consume => " + uuid);
                        empty.signal();
                        break;
                    } catch (Exception e) {
                        e.printStackTrace();
                        break;
                    } finally {
                        lock.unlock();
                    }
                }
            }, 1, 3, TimeUnit.SECONDS);
        }

    }
}
